home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / NR4.C < prev    next >
C/C++ Source or Header  |  1990-05-20  |  18KB  |  725 lines

  1. /* NET/ROM level 4 processing */
  2.  
  3. #include <stdio.h>
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "iface.h"
  7. #include "trace.h"
  8. #include "timer.h"
  9. #include "arp.h"
  10. #include "ax25.h"
  11. #include "netrom.h"
  12.  
  13. #ifdef NETROM4
  14. unsigned nr_trtimeout = 60;
  15. unsigned nr_trtries = 3;
  16. unsigned nr_trackdelay = 3;
  17. unsigned nr_trbusdelay = 180;
  18. unsigned nr_trwindow = 4;
  19. unsigned nr_trbacklog = 4;
  20. unsigned nr_noactive = 900;
  21.  
  22. struct nr_circ *nr_circ[NR4NUMCIRC];    /* the circuit table */
  23. #endif
  24.  
  25. extern char badcall[];
  26.  
  27. static void nr4_connect(),nr4ack(),nr4_state(),nr4_reset(),nrtrtime(),nrtrack();
  28. static int nr4sendit();
  29. static struct nr_circ *nr4_circptr(),*nr4_newcirc();
  30. void nr4_close();
  31.  
  32. /* send IP datagrams across a NET/ROM network connection */
  33. int
  34. nr_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  35. struct mbuf *bp;
  36. struct interface *interface;        /* the "netrom" pseudo-iface */
  37. int32 gateway;
  38. char precedence;
  39. char delay;
  40. char throughput;
  41. char reliability;
  42. {
  43.     struct arp_tab *arp;
  44.     struct mbuf *hbp;
  45.     struct nr4hdr n4hdr;
  46.     struct ax25_addr dest;
  47.  
  48.     dump(interface,IF_TRACE_OUT,TRACE_IP,bp); /* trace to "netrom" */
  49.  
  50.     if ((arp = arp_lookup(interface,ARP_NETROM,gateway)) == NULLARP) {
  51.         free_p(bp);        /* drop the packet if no route */
  52.         return -1;
  53.     }
  54.  
  55.     /* new NET/ROM encapsulation method: put a  NET/ROM transport */
  56.     /* header with opcode=protocol extension before the IP packet */
  57.     n4hdr.opcode = NR4PID;
  58.     n4hdr.family = PID_IP;
  59.     n4hdr.proto  = PID_IP;
  60.     if ((hbp = htonnr4(&n4hdr)) == NULLBUF) {
  61.         free_p(bp);        /* no space for level4 header */
  62.         return -1;
  63.     }
  64.     hbp->next = bp;
  65.  
  66.     getaxaddr(&dest,arp->hw_addr);    /* get destination call */
  67.     return nr_send3(hbp,&dest);    /* send it to level 3 */
  68. }
  69.  
  70. /* Process NET/ROM transport layer packets.
  71.  */
  72. void
  73. nr4recv(bp)
  74. struct mbuf *bp;
  75. {
  76.     struct nr4hdr n4hdr;
  77.     struct mbuf *bph;
  78.     register struct nr_circ *circ;
  79.  
  80.     if (ntohnr4(&n4hdr,&bp) < 0) {        /* get transport header */
  81.         free_p(bp);            /* bad header, ignore it */
  82.         return;
  83.     }
  84.  
  85.     switch (n4hdr.opcode & NR4OMASK) {    /* look at opcode bits */
  86.     case NR4PID:                /* network protocol extension */
  87.         if (n4hdr.family == PID_IP &&    /* is it IP family? */
  88.             n4hdr.proto == PID_IP)    /* IP protocol? */
  89.             ip_route(bp,0);        /* send to the IP router */
  90.         else
  91.             free_p(bp);            /* something else, ignore */
  92.         return;
  93.  
  94.     case NR4CONRQ:                /* connect request */
  95.         nr4_connect(&n4hdr);
  96.  
  97.         if ((bph = htonnr4(&n4hdr)) != NULLBUF)
  98.             nr_send3(bph,&n4hdr.snode);
  99.         break;
  100.  
  101. #ifdef NETROM4
  102.     case NR4CONACK:                /* connect acknowledge */
  103.         if ((circ = nr4_circptr(&n4hdr)) != NULLNRCIRC &&
  104.             circ->state == NR4STCPEND){
  105.             if (n4hdr.opcode & NR4CREFUSE) {
  106.             circ->d_reason = NR4REBUSY;
  107.             nr4_reset(circ);
  108.             } else {
  109.             ASSIGN(circ->your,n4hdr.my);
  110.             circ->window = min(n4hdr.window,nr_trwindow);
  111.             stop_timer(&circ->trtimer);
  112.             nr4_state(circ,NR4STCON);
  113.             }
  114.         }
  115.         break;
  116.  
  117.     case NR4DISRQ:                /* disconnect request */
  118.         if ((circ = nr4_circptr(&n4hdr)) != NULLNRCIRC){
  119.             ASSIGN(n4hdr.your,circ->your);
  120.             n4hdr.my.index = n4hdr.my.id = 0;
  121.             n4hdr.opcode = NR4DISACK;
  122.  
  123.             if ((bph = htonnr4(&n4hdr)) != NULLBUF)
  124.             nr_send3(bph,&circ->dnode);
  125.  
  126.             nr4_reset(circ);
  127.         }
  128.         break;
  129.  
  130.     case NR4DISACK:                /* disconnect acknowledge */
  131.         if ((circ = nr4_circptr(&n4hdr)) != NULLNRCIRC &&
  132.             circ->state == NR4STDPEND){
  133.             nr4_reset(circ);
  134.         }
  135.         break;
  136.  
  137.     case NR4INFO:                /* information */
  138.         if ((circ = nr4_circptr(&n4hdr)) != NULLNRCIRC &&
  139.             circ->state == NR4STCON){
  140.             start_timer(&circ->acktimer);/* send ACK/NAK after a while */
  141.                         /* unless someone below does it */
  142.  
  143.             if (circ->rxseq == n4hdr.txseq){ /* check sequence# */
  144.             circ->rxseq = n4hdr.txseq + 1; /* ok, update */
  145.             circ->mystate &= ~NR4NAK;
  146.             nr4ack(circ,&n4hdr);    /* process ACK information */
  147.  
  148.             append(&circ->rxasm,bp);/* assemble packets */
  149.             bp = NULLBUF;
  150.  
  151.             if (!(n4hdr.opcode & NR4MORE)) { /* not MORE coming? */
  152.                 enqueue(&circ->rxq,circ->rxasm);
  153.                 circ->rxasm = NULLBUF;
  154.  
  155.                 if (circ->r_upcall != NULLVFP)
  156.                 (*circ->r_upcall)(circ,len_q(circ->rxq));
  157.  
  158.                 if (len_q(circ->rxq) >= nr_trbacklog)
  159.                 circ->mystate |= NR4CHOKE;
  160.             }
  161.  
  162.             start_timer(&circ->noacttim); /* kick no-activity */
  163.             } else {            /* bad sequence # */
  164.             if (uchar(n4hdr.txseq - circ->rxseq) <= circ->window)
  165.                 circ->mystate |= NR4NAK; /* in window, NAK it */
  166.                         /* (others are ignored) */
  167.  
  168.             nr4ack(circ,&n4hdr);    /* process ACK information */
  169.             }
  170.         }
  171.         break;
  172.  
  173.     case NR4INFACK:                /* information acknowledge */
  174.         if ((circ = nr4_circptr(&n4hdr)) != NULLNRCIRC &&
  175.             circ->state == NR4STCON)
  176.             nr4ack(circ,&n4hdr);    /* process it */
  177.         break;
  178. #endif
  179.     }
  180.  
  181.     free_p(bp);                /* free anything left over */
  182. }
  183.  
  184. /* attach the NET/ROM interface.  optionally set NET/ROM call too. */
  185. int
  186. nr_attach(argc,argv)
  187. int argc;
  188. char *argv[];
  189. {
  190.     register struct ax25_call *axc;
  191.     struct ax25_addr hwaddr;
  192.  
  193.     if (nr_interface != NULLIF) {
  194.         printf("netrom interface already attached\n");
  195.         return -1;
  196.     }
  197.  
  198.     if (argc > 1) {
  199.         if (setcall(&hwaddr,argv[1]) < 0) {
  200.             printf(badcall,argv[1]);
  201.             return -1;
  202.         }
  203.  
  204.         if((axc = cr_axcall(ax25_call,&hwaddr)) == NULLAXCALL)
  205.             return -1;
  206.  
  207.         axc->flags |= MULTI_IF;
  208.     }
  209.  
  210.     nr_arp();
  211.  
  212.     if((nr_interface = (struct interface *)calloc(1,sizeof(struct interface))) == NULLIF)
  213.         return -1;
  214.     nr_interface->name = "netrom";
  215.     nr_interface->mtu = NR4ILEN;
  216.     nr_interface->send = nr_send;
  217.     if (argc > 1){            /* callsign specified? */
  218.         if((nr_interface->hwaddr = malloc(sizeof(struct ax25_addr))) == NULLCHAR)
  219.             return -1;
  220.         memcpy(nr_interface->hwaddr,(char *)&hwaddr,sizeof(struct ax25_addr));
  221.     }
  222.  
  223.     nr_interface->next = ifaces;
  224.     ifaces = nr_interface;
  225.     return 0;
  226. }
  227.  
  228. /* process incoming level 4 connect requests */
  229.  
  230. static void
  231. nr4_connect (hdr)
  232. register struct nr4hdr *hdr;
  233. {
  234.     register struct nr_circ *circ;
  235.     extern void nr7_rxnr();
  236.  
  237.     /* setup default response to reject the connect request */
  238.     ASSIGN(hdr->your,hdr->my);
  239.     hdr->my.index = hdr->my.id = 0;
  240.     hdr->opcode = NR4CONACK | NR4CREFUSE;
  241.  
  242. #ifdef NETROM4
  243.     if (nr_trtimeout < 60 ||        /* NET/ROM 4 inoperable? */
  244.         nr_trtries == 0 ||
  245.         nr_trackdelay == 0 ||
  246.         nr_trbusdelay < 60 ||
  247.         nr_trwindow == 0 ||
  248.         nr_noactive < 60)
  249.         return;                /* reject connection */
  250.  
  251.     if (hdr->window == 0 ||            /* bad window? */
  252.         valid_addr(&hdr->suser) != 0 ||    /* invalid source call? */
  253.         valid_addr(&hdr->snode) != 0)    /* invalid source node? */
  254.         return;                /* reject it */
  255.  
  256.     if ((circ = nr4_newcirc(&hdr->your,&hdr->snode)) == NULLNRCIRC)
  257.         return;                /* no space, refuse it */
  258.  
  259.     /* got a circuit, initialize it and build CONACK */
  260.  
  261.     ASSIGN(hdr->my,circ->my);
  262.     hdr->window = circ->window = min(hdr->window,nr_trwindow);
  263.     ASSIGN(circ->suser,hdr->suser);
  264.  
  265.     nr4_state(circ,NR4STCON);
  266.  
  267.     circ->trtimer.start = SEC2TICK(nr_trtimeout);
  268.     circ->trtimer.func = nrtrtime;
  269.  
  270.     circ->acktimer.start = SEC2TICK(nr_trackdelay);
  271.     circ->acktimer.func = nrtrack;
  272.  
  273.     circ->noacttim.start = SEC2TICK(nr_noactive);
  274.     circ->noacttim.func = nr4_close;
  275.  
  276.     circ->trtimer.arg = circ->acktimer.arg = circ->noacttim.arg = (char *) circ;
  277.  
  278.     start_timer(&circ->noacttim);        /* start no-activity timer */
  279.  
  280.     circ->r_upcall = nr7_rxnr;        /* receive = NET/ROM cmds */
  281.  
  282.     hdr->opcode &= ~NR4CREFUSE;        /* accept connection */
  283. #endif
  284. }
  285.  
  286. #ifdef NETROM4
  287. /* connect a NET/ROM l4 circuit */
  288.  
  289. struct nr_circ *
  290. nr4_conn (dnode,snode,suser,r_upcall,t_upcall,s_upcall,user)
  291. struct ax25_addr *dnode;    /* destination node's call */
  292. struct ax25_addr *snode;    /* originating node's call */
  293. struct ax25_addr *suser;    /* originating user's call */
  294. void (*r_upcall)();        /* Receiver upcall handler */
  295. void (*t_upcall)();        /* Transmitter upcall handler */
  296. void (*s_upcall)();        /* State-change upcall handler */
  297. char *user;            /* user ctrlblock pointer */
  298.  
  299. {
  300.     register struct nr_circ *circ;
  301.     int idx;
  302.  
  303.     if (nr_trtimeout < 60 ||        /* NET/ROM 4 inoperable? */
  304.